package cn.mrcode.wxsdk.core.dialogue.common.accessToken.lifeCycle.distributed.strategy.master_old;

import cn.mrcode.wxsdk.core.dialogue.common.LogUtil;
import cn.mrcode.wxsdk.core.dialogue.common.accessToken.AccessTokenApi;
import cn.mrcode.wxsdk.core.dialogue.common.distributed.ZkDistributedSingleNodeExecutor;
import cn.mrcode.wxsdk.core.dialogue.common.exception.ReqException;
import cn.mrcode.wxsdk.core.dialogue.common.exception.WxException;
import cn.mrcode.wxsdk.core.dialogue.common.log.LogTemplateUtil;
import cn.mrcode.wxsdk.core.dialogue.common.util.DateUtil;
import cn.mrcode.wxsdk.core.dialogue.protocol.base.AccessTokenInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.DelayQueue;

/**、
 * 维护生命周期的分布式服务
 * @author zhuqiang
 * @version V1.0
 * @date 2015/9/22 17:22
 */
@Deprecated
public class AccessTokenDistributedTask implements Runnable{
    private static Logger log = LoggerFactory.getLogger(AccessTokenDistributedTask.class);
    private ZkDistributedSingleNodeExecutor zsnf;
    private ConcurrentHashMap<String, AccessTokenInfo> taskMap;  //用于任务中 更新的 token 列表.全部打成数组上传 zk上
    private DelayQueue<AccessTokenInfo> queue; // 队列中的数据 和 taskMap一致。也需要事先准备好给task

    /**
     *
     * @param zsnf
     * @param taskMap map中的token不会动态增加了
     */
    public AccessTokenDistributedTask(ZkDistributedSingleNodeExecutor zsnf,ConcurrentHashMap<String, AccessTokenInfo> taskMap) {
        this.zsnf = zsnf;
        this.taskMap = taskMap;
        queue = new DelayQueue<AccessTokenInfo>();
        for (Map.Entry<String,AccessTokenInfo> ent : taskMap.entrySet()){
            queue.add(ent.getValue());
        }
    }

    @Override
    public void run() {
        String apiName = "分布式AccessTokenTask";
        while (true) {
            try {
                queue.clear();
                for (Map.Entry<String,AccessTokenInfo> ent : taskMap.entrySet()){
                    queue.add(ent.getValue());
                }
                log.info(LogTemplateUtil.svMsg(apiName,"taskMap.size=%s;queue.size=%s",taskMap.size()+"",queue.size()+""));
                AccessTokenInfo ati = queue.take();  //获取超时的 对象
                log.info(LogTemplateUtil.svMsg(apiName,"%s,id=%s;获取到超时AccessTokenInfo，数据=%s；超时时间=%s",
                        zsnf.getRootPath(),zsnf.getThisPath(),
                        JSONObject.toJSONString(ati), DateUtil.lFormat(ati.getTimeOut())));
                String appID = ati.getAppID();
                if(taskMap.containsKey(appID)){
                    try {
                        ati = AccessTokenApi.getAccessTokenInfo(appID, ati.getAppSecret(),zsnf.getThisPath());
                    } catch (ReqException e) {
                        log.error(LogTemplateUtil.svMsg(apiName,"%s,id=%s;appid=%s;" + LogUtil.fromateLog(e),zsnf.getRootPath(),zsnf.getThisPath(),appID));
                    } catch (WxException e) {
                        log.error(LogTemplateUtil.svMsg(apiName,"%s,id=%s;appid=%s;" + LogUtil.fromateLog(e),zsnf.getRootPath(),zsnf.getThisPath(),appID));
                    }
                    taskMap.put(appID, ati);
                    queue.add(ati);
                    log.info(LogTemplateUtil.svMsg(apiName,"%s,id=%s;appID=%s 已经更新；新的JsApiTicketInfo数据=%s；超时时间=%s",
                            zsnf.getRootPath(),zsnf.getThisPath(),
                            appID,JSONObject.toJSONString(ati), DateUtil.lFormat(ati.getTimeOut())));
                    //写入 zk上
                    Collection<AccessTokenInfo> values = taskMap.values();
                    List<AccessTokenInfo> data = new ArrayList<AccessTokenInfo>(values);
                    zsnf.writeData(JSON.toJSONString(data));
                }else{
                    log.error(LogTemplateUtil.svMsg(apiName,"taskMap中不包含该appid(%s),忽略处理",appID));
                }
            } catch (InterruptedException e) {
                log.error(LogTemplateUtil.svMsg(apiName,"%s,id=%s;任务被中断，异常信息=%s",zsnf.getRootPath(),zsnf.getThisPath(),JSONObject.toJSONString(e)));
            }
        }
    }
}
